// * 现代设置/获取原型的方法
// * Object.setPrototypeOf(obj, proto) —— 将 对象 的 [[prototype]]原型 设置为 proto。
// * Object.getPrototypeOf(obj) —— 返回 对象 的 [[prototype]]原型。
// * Object.create(proto, [descriptors]) —— 使用 proto 作为 [[prototype]]原型 和可选的属性描述来创建一个空对象。

// * 例子：
let animal = {
	eats: true,
}

// 创建一个以 animal 为原型的新对象
let rabbit = Object.create(animal)
console.log(rabbit.eats) // true
console.log(Object.getPrototypeOf(rabbit) === animal) // true
console.log(rabbit.eats) // true
// 将 rabbit 的原型设置为 {}
Object.setPrototypeOf(rabbit, {})
console.log(rabbit.eats) // undefined

// * Object.create 第二个属性描述符参数
let obj = { name: 'Jake' }
let newObj = Object.create(obj, {
	propName: {
		value: true,
	},
})

console.log(newObj.propName, newObj.name) // true Jake

// * 完全拷贝一个对象的方式，此方式可以完全拷贝对象的所有属性，可枚举和不可枚举的，数据属性 和 访问器属性，包括所有内容，并且带有正确的原型链。
let clone = Object.create(
	Object.getPrototypeOf(obj), // 获取 obj 的原型
	Object.getOwnPropertyDescriptors(obj) // 获取 obj 的所有属性及其描述符
)

// ***********************************************************************************************************************************************

// * 创建一个没有[[prototype]]原型的对象（因为原型要么是对一个对象的引用，要么是 null）
let obj2 = Object.create(null) // 等价于 { __proto__: null }

// Object.setPrototypeOf(obj2, { name: '我是原型对象' }) // 设置原型有效
obj2.__proto__ = { name: '我是原型对象' } // 设置原型对象无效。 __proto__ 是专门针对 [[prototype]] 进行set/get的，这个对象连 [[prototype]] 都没有，所以也就没有 __proto__ 设置原型的属性了。

console.log('obj2', obj2.name) // obj2 undefined
console.log('obj2', obj2.__proto__) // obj2 { name: '我是原型对象' }
console.log(Object.getPrototypeOf(obj2)) // null

// * 不推荐使用内建的 __proto__ getter/setter 获取/设置原型。
// * 原型为 null 时，对象才真正是空的。
